using System;
using System.Collections.Generic;
using System.Text;

namespace Fuzzy
{
    /// <summary>
    /// A class representing a fuzzy linguistic variable.
    /// </summary>
    public class FuzzyLinguisticVariable
    {
        private string name;

        /// <summary>
        /// Gets or sets the name of the fuzzy linguistic variable.
        /// </summary>
        public string Name
        {
            get { return name; }
        }

        private double domainMin;

        /// <summary>
        /// Gets or sets the minimum value of the the fuzzy linguistic variable's domain.
        /// </summary>
        public double DomainMin
        {
            get { return domainMin; }
        }

        private double domainMax;

        /// <summary>
        /// Gets or sets the maximum value of the the fuzzy linguistic variable's domain.
        /// </summary>
        public double DomainMax
        {
            get { return domainMax; }
        }

        /// <summary>
        /// Creates a fuzzy linguistic variable.
        /// </summary>
        /// <param name="name">The name of the fuzzy linguistic variable.</param>
        /// <param name="domainMin">The minimum of the linguistic variable's domain.</param>
        /// <param name="domainMax">The maximum of the linguistic variable's domain.</param>
        public FuzzyLinguisticVariable(string name, double domainMin, double domainMax)
        {
            this.name = name;
            this.domainMin = domainMin;
            this.domainMax = domainMax;
            
        }

        /// <summary>
        /// It creates a Rubini-partition where the membership functions are triangular 
        /// except near the edge of the domain.
        /// </summary>
        /// <param name="points">The peaks of the triangles.</param>
        /// <returns>An array consisting the created fuzzy sets.</returns>
        public PieceWiseLinearFuzzySet[] CreateRuspiniPartition(double[] points)
        {
            PieceWiseLinearFuzzySet[] fuzzySets = new PieceWiseLinearFuzzySet[points.Length];
            fuzzySets[0] = new PieceWiseLinearFuzzySet(this, new double[] { points[0], points[1] }, new double[] { 1.0, 0.0 });
            for (int i = 0; i < points.Length - 2; i++)
            {
                fuzzySets[i+1] = new TriangularFuzzySet(this, new double[] { points[i], points[i + 1], points[i + 2] }, new double[] { 0.0, 1.0, 0.0 });
            }
            fuzzySets[points.Length - 1] = new PieceWiseLinearFuzzySet(this, new double[] { points[points.Length - 2], points[points.Length - 1] }, new double[] { 0.0, 1.0 });
            return fuzzySets;
        }

        /// <summary>
        /// It creates a Rubini-partition where the membership functions are triangular 
        /// except near the edge of the domain.
        /// </summary>
        /// <param name="names">The terms of the partitions.</param>
        /// <param name="points">The peaks of the triangles.</param>
        /// <returns>An array consisting the created fuzzy sets.</returns>
        public PieceWiseLinearFuzzySet[] CreateRuspiniPartition(string[] names, double[] points)
        {
            if (names.Length != points.Length)
                throw new FuzzyException("Each fuzzy set must have a name.");
            PieceWiseLinearFuzzySet[] fuzzySets = new PieceWiseLinearFuzzySet[points.Length];
            fuzzySets[0] = new PieceWiseLinearFuzzySet(this, names[0], new double[] { points[0], points[1] }, new double[] { 1.0, 0.0 });
            for (int i = 0; i < points.Length - 2; i++)
            {
                fuzzySets[i + 1] = new TriangularFuzzySet(this, names[i + 1], new double[] { points[i], points[i + 1], points[i + 2] }, new double[] { 0.0, 1.0, 0.0 });
            }
            fuzzySets[points.Length - 1] = new PieceWiseLinearFuzzySet(this, names[points.Length - 1], new double[] { points[points.Length - 2], points[points.Length - 1] }, new double[] { 0.0, 1.0 });
            return fuzzySets;
        }
    }
}
